<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="js/common/three.js"></script>
		<script src="js/OrbitControls.js"></script>
		<script src="js/data/ChinaJson.js"></script>
		<script src="js/data/chinaBounDary.js"></script>
		<style>
			body {
				margin: 0;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
	<!-- 	<script id="vertexShader2" type="x-shader/x-vertex">
		    varying vec2 vUv;
		    attribute float percent;
		    uniform float u_time;
		    uniform float number;
		    uniform float speed;
		    uniform float length;
		    varying float opacity;
		    uniform float size;
		    void main()
		    {
		        vUv = uv;
		        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
		        float l = clamp(1.0-length,0.0,1.0);
		        gl_PointSize = clamp(fract(percent*number + l - u_time*number*speed)-l ,0.0,1.) * size * (1./length);
		        opacity = gl_PointSize/size;
		        gl_Position = projectionMatrix * mvPosition;
		    }
		</script>
		<script id="fragmentShader2" type="x-shader/x-fragment">
		    #ifdef GL_ES
		    precision mediump float;
		    #endif
		    varying float opacity;
		    uniform vec3 color;
		    void main(){
		        if(opacity <=0.2){
		            discard;
		        }
		        gl_FragColor = vec4(color,1.0);
		    }
		</script> -->
		<script>
		// const singleUniforms = {
		//             u_time: uniforms2.u_time,
		//             number: { type: 'f', value: number },
		//             speed: { type: 'f', value: speed },
		//             length: { type: 'f', value: length },
		//             size: { type: 'f', value: size },
		//             color: { type: 'v3', value: color }
		// };
			// console.log(chinaJson)
			//创建一个场景，相当于一个房间，
			const scene = new THREE.Scene();
			group = new THREE.Group();
			var globeTextureLoader = new THREE.TextureLoader();
			let object = new THREE.Object3D()
			let radius = 18;
			//PerspectiveCamera 透视摄像机，OrthograhicCamera正交摄像机
			const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
			// camera.lookAt(0, 3, 0);
			//把摄像机往外面移动
			camera.position.z = 50;
			//渲染器
			const renderer = new THREE.WebGLRenderer({
				antialias: true,
				alpha: true
			});
			//设置渲染器尺寸
			renderer.setPixelRatio(window.devicePixelRatio);
			renderer.setSize(window.innerWidth, window.innerHeight);
			renderer.setClearColor(0x000000, 0.9);
			//添加到html中
			document.body.appendChild(renderer.domElement);

			//随机生成星光
			function stars() {
				const positions = [];
				const colors = [];
				const geometry = new THREE.BufferGeometry();
				let texture = new globeTextureLoader.load('./img/光点1.png')
				for (var i = 0; i < 10000; i++) {
					var vertex = new THREE.Vector3();
					vertex.x = Math.random() * 2 - 1;
					vertex.y = Math.random() * 2 - 1;
					vertex.z = Math.random() * 2 - 1;
					positions.push(vertex.x, vertex.y, vertex.z);
					var color = new THREE.Color();
					color.setHSL(Math.random() * 0.2 + 0.5, 0.55, Math.random() * 0.25 + 0.55);
					colors.push(color.r, color.g, color.b);
				}
				geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
				geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
				var starsMaterial = new THREE.ParticleBasicMaterial({
					map: texture,
					size: 1,
					transparent: true,
					opacity: 1,
					vertexColors: true, //true：且该几何体的colors属性有值，则该粒子会舍弃第一个属性--color，而应用该几何体的colors属性的颜色
					blending: THREE.AdditiveBlending,
					sizeAttenuation: true
				});
				let stars = new THREE.ParticleSystem(geometry, starsMaterial);
				stars.scale.set(300, 300, 300);
				scene.add(stars);
			}
			stars();

			//光晕
			function initSprite() {
				const texture = globeTextureLoader.load('./img/光晕.png');
				const spriteMaterial = new THREE.SpriteMaterial({
					map: texture,
					transparent: true,
					opacity: 0.5,
					depthWrite: false
				});
				const sprite = new THREE.Sprite(spriteMaterial);
				sprite.scale.set(radius * 3, radius * 3, 1);
				sprite.position.set(0.5, 2.9, 0.1);
				scene.add(sprite);
			}
			// initSprite()
			//星空背景
			function initBg() {
				// 加载星空纹理
				const texture = globeTextureLoader.load('./img/taikong.jpg');
				// 生成球体
				const sphereGeometry = new THREE.SphereGeometry(1000, 50, 50);
				// 调转球体正反
				sphereGeometry.scale(-1, 1, 1);
				// 赋予纹理贴图
				const sphereMaterial = new THREE.MeshBasicMaterial({
					map: texture
				});
				// 生成几何球体
				sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
				// 放入场景内
				scene.add(sphere);
			}
			initBg()
			/**
			 *lng:经度
			 *lat:维度
			 *radius:地球半径
			 */
			function lglt2xyz(lng, lat, radius) {
				const theta = (90 + lng) * (Math.PI / 180)
				const phi = (90 - lat) * (Math.PI / 180)
				return (new THREE.Vector3()).setFromSpherical(new THREE.Spherical(radius, phi, theta))
			}
			// function lglt2xyz(longitude, latitude,R) {
			//     const lon = longitude * Math.PI / 180;
			//     const lat = latitude * Math.PI / 180;
			//     const x = R * Math.cos(lat) * Math.sin(lon);
			//     const y = R * Math.sin(lat);
			//     const z = R * Math.cos(lon) * Math.cos(lat);
			//     return { x, y, z };
			// }

			//生成地球
			function earth() {
				globeTextureLoader.load('./img/earth.jpg', function(texture) {
					const geometry = new THREE.SphereGeometry(radius, 100, 100);
					const material = new THREE.MeshStandardMaterial({
						map: texture
					});
					const sphere = new THREE.Mesh(geometry, material);
					group.rotation.set(0.5, 2.9, 0.1);
					group.add(sphere);
				});
				scene.add(group)
			}
			earth()
			//光柱
			function lightCross(pos) {
				var groupMesh = new THREE.Group()
				var plane = new THREE.PlaneGeometry(4, 4)
				var textureLoader = new THREE.TextureLoader();
				var material = new THREE.MeshPhongMaterial({
					//设置矩形网格模型的纹理贴图(光柱特效)
					map: textureLoader.load('./img/lightCross.png'),
					// 双面显示
					side: THREE.DoubleSide,
					// 开启透明效果，否则颜色贴图map的透明不起作用
					transparent: true,
				});
				var mesh1 = new THREE.Mesh(plane, material);
				// 克隆网格模型mesh1，并旋转90度
				var mesh2 = mesh1.clone().rotateY(Math.PI / 2)
				groupMesh.add(mesh1, mesh2);
				groupMesh.position.set(pos.x, pos.y, pos.z)
				groupMesh.rotateX(Math.PI / 2)
				groupMesh.name = "光柱"
				scene.add(groupMesh);
			}
			// lightCross()

			//构建中国各省级轮廓
			function initMap(ChinaJson) {
				var groupMesh = new THREE.Group()
				// 遍历省份构建模型
				ChinaJson.features.forEach(elem => {
					// 新建一个省份容器：用来存放省份对应的模型和轮廓线
					const province = new THREE.Object3D();
					const coordinates = elem.geometry.coordinates;
					coordinates.forEach(multiPolygon => {
						multiPolygon.forEach(polygon => {
							const lineMaterial = new THREE.LineBasicMaterial({
								color: 0XF19553
							}); //0x3BFA9E
							const positions = [];
							const linGeometry = new THREE.BufferGeometry();
							for (let i = 0; i < polygon.length; i++) {
								var pos = lglt2xyz(polygon[i][0], polygon[i][1], radius);
								positions.push(pos.x, pos.y, pos.z);
							}
							linGeometry.setAttribute('position', new THREE.Float32BufferAttribute(
								positions, 3));
							const line = new THREE.Line(linGeometry, lineMaterial);
							province.add(line);
						});
					});
					groupMesh.add(province);
				});
				// console.log(groupMesh)
				group.add(groupMesh);
			}
			initMap(chinaJson)
			
			//构建中国轮廓,使用流光效果
			function initChinaMap(ChinaJson) {
				var groupMesh = new THREE.Group()
			
				// 遍历省份构建模型
				ChinaJson.features.forEach(elem => {
					// 新建一个省份容器：用来存放省份对应的模型和轮廓线
					const province = new THREE.Object3D();
					const coordinates = elem.geometry.coordinates;
					coordinates.forEach(multiPolygon => {
						multiPolygon.forEach(polygon => {
							  let shaderMaterial = new THREE.ShaderMaterial({
							        // uniforms: singleUniforms,
							        // vertexShader: document.getElementById('vertexShader2').textContent,
							        // fragmentShader: document.getElementById('fragmentShader2').textContent,
							        blending: THREE.AdditiveBlending,
							        depthTest: false,// 这个不设置的话，会导致带透明色的贴图始终会有方块般的黑色背景
							        transparent: true
							    });
							const positions = [];
							const linGeometry = new THREE.BufferGeometry();
							for (let i = 0; i < polygon.length; i++) {
								var pos = lglt2xyz(polygon[i][0], polygon[i][1], radius);
								positions.push(pos.x, pos.y, pos.z);
							}
							linGeometry.setAttribute('position', new THREE.Float32BufferAttribute(
								positions, 3));
							const point = new THREE.Points(linGeometry, shaderMaterial);
							province.add(point);
						});
					});
					groupMesh.add(province);
				});
				// console.log(groupMesh)
				group.add(groupMesh);
			}
			initChinaMap(chinaBounJson)
			//标注以及标注扩散光圈
			function createPointMesh(pos, texture) {
				const planGeometry = new THREE.PlaneBufferGeometry(1, 1);
				var material = new THREE.MeshBasicMaterial({
					map: texture,
					transparent: true, //使用背景透明的png贴图，注意开启透明计算
					// side: THREE.DoubleSide, //双面可见
					depthWrite: false, //禁止写入深度缓冲区数据  这个不设置的话，会导致带透明色的贴图始终会有方块般的黑色背景
				});
				var mesh = new THREE.Mesh(planGeometry, material);
				var size = radius * 0.04; //矩形平面Mesh的尺寸
				mesh.scale.set(size, size, size); //设置mesh大小
				//设置mesh位置
				mesh.position.set(pos.x, pos.y, pos.z);
				// mesh在球面上的法线方向(球心和球面坐标构成的方向向量)
				var coordVec3 = new THREE.Vector3(pos.x, pos.y, pos.z).normalize();
				// mesh默认在XOY平面上，法线方向沿着z轴new THREE.Vector3(0, 0, 1)
				var meshNormal = new THREE.Vector3(0, 0, 1);
				// 四元数属性.quaternion表示mesh的角度状态
				//.setFromUnitVectors();计算两个向量之间构成的四元数值
				mesh.quaternion.setFromUnitVectors(meshNormal, coordVec3);
				
				return mesh;
			}
			//初始化标注
			function initMarks() {
				const arr = {
					longitude: -83.320004,
					latitude: -6.82402,
				}
				// const arr = {longitude:108,latitude:22, }
				let pos = lglt2xyz(arr.longitude, arr.latitude, radius);
				// 加载星空纹理
				const texture = globeTextureLoader.load('./img/标注.png');
				scene.add(createPointMesh(pos, texture));
				lightCross(pos);
			}
			initMarks()
			//灯光
			function initLight() {
				const ambientLight = new THREE.AmbientLight(0xcccccc, 1.1);
				scene.add(ambientLight);

				var directionalLight = new THREE.DirectionalLight(0xffffff, 0.2);
				directionalLight.position.set(1, 0.1, 0).normalize();
				var directionalLight2 = new THREE.DirectionalLight(0xff2ffff, 0.2);
				directionalLight2.position.set(1, 0.1, 0.1).normalize();
				scene.add(directionalLight);
				scene.add(directionalLight2);

				var hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.2);
				hemiLight.position.set(0, 1, 0);
				scene.add(hemiLight);

				var directionalLight = new THREE.DirectionalLight(0xffffff);
				directionalLight.position.set(1, 500, -20);
				directionalLight.castShadow = true;
				directionalLight.shadow.camera.top = 18;
				directionalLight.shadow.camera.bottom = -10;
				directionalLight.shadow.camera.left = -52;
				directionalLight.shadow.camera.right = 12;
				scene.add(directionalLight);
			}
			
			//鼠标点击事件
			function click(){
				document.body.addEventListener("mousedown", (event) => {
				    let mouse = new THREE.Vector2();
				    let raycaster = new THREE.Raycaster();
				    // 计算鼠标点击位置转换到3D场景后的位置
				    mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
				    mouse.y = -(event.clientY / renderer.domElement.clientHeight) * 2 + 1;
				    // 由当前相机（视线位置）像点击位置发射线
				    raycaster.setFromCamera(mouse, camera);
				    let intersects = raycaster.intersectObjects(scene.children, true)
				    if (intersects.length > 0) {
				        // 拿到射线第一个照射到的物体
				        console.log(intersects[0].object);
				    }
				});
			}
			// click()
			//相机控制
			var orbitControl = new THREE.OrbitControls(camera, renderer.domElement);
			orbitControl.enableDamping = true;
			// this.orbitControl.autoRotate=true;
			orbitControl.dampingFactor = 0.5;
			// 视角最小距离
			orbitControl.minDistance = 0;
			// 视角最远距离
			orbitControl.maxDistance = 1000;

			const animate = function() {
				//创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环
				requestAnimationFrame(animate);

				// cube.rotation.x += 0.01;
				// cube.rotation.y += 0.01;

				// group.rotation.x += 0.001;
				// group.rotation.y += 0.001;
				renderer.render(scene, camera);
			};
			initLight()
			animate();
		</script>
		<h1>111</h1>
	</body>
</html>
